package com.xquant.trade.trade.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageInfo;
import com.xquant.common.core.constant.DictConstant;
import com.xquant.common.core.constant.SummitConstants;
import com.xquant.common.core.utils.ParseUtils;
import com.xquant.common.engine.xPP.cxf.NotifyDataFacade;
import com.xquant.common.log.service.AsyncLogService;
import com.xquant.common.security.utils.SecurityUtils;
import com.xquant.trade.account.service.CounterpartyService;
import com.xquant.trade.trade.entity.*;
import com.xquant.trade.trade.mapper.TradeMapper;
import com.xquant.trade.trade.service.TradeService;
import com.xquant.trade.utils.CacheUtil;
import com.xquant.trade.utils.CommResponse;
import com.xquant.trade.utils.TradeValidatedUtil;
import com.xquant.trade.utils.TransferUtil;
import com.xquant.system.api.RemoteDailyPriceService;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;

@Component
public class TradeServiceImpl {

    @Autowired
    private TradeMapper tradeMapper;
    @Autowired
    private TradeServiceFactory tradeServiceFactory;

    @Autowired
    private RemoteDailyPriceService remoteDailyPriceService;

    @Autowired
    private NotifyDataFacade notifyDataFacade;


    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * newCloud service 查询场内交易
     */
    public List<InnerTrade> querySimpleTradeByPage(Map map) {
        map.put("userId", SecurityUtils.getUserId());
        String instruments = MapUtils.getString(map, "instruments");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(instruments)) {
            map.put("instruments", instruments.split("\\|"));
        }
        String accIds = MapUtils.getString(map, "accIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(accIds)) {
            map.put("accIds", accIds.split(","));
        }
        String tradeTypes = MapUtils.getString(map, "tradeTypes");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(tradeTypes)) {
            map.put("tradeTypes", tradeTypes.split(","));
        }
        return tradeMapper.querySimpleTradeByPage(map);
    }

    public Map<String, Object> getMarketPrice(Map<String, Object> param) {
        return tradeMapper.getMarketPrice(param);
    }

    /**
     * newCloud service 分组查询场内交易
     */
    public List<TradeGroupDTO> querysimpleTradeGroup(Map map) {
        if (StrUtil.isNotBlank(MapUtils.getString(map, "accIds"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "accIds")).size() > 0) {
                map.put("accIds", JSONUtil.parseArray(MapUtils.getString(map, "accIds")).toArray(String.class));
            } else {
                map.put("accIds", null);
            }
        }
        if (StrUtil.isNotBlank(MapUtils.getString(map, "tradeTypes"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "tradeTypes")).size() > 0) {
                map.put("tradeTypes", JSONUtil.parseArray(MapUtils.getString(map, "tradeTypes")).toArray(String.class));
            } else {
                map.put("tradeTypes", null);
            }
        }
        if (StrUtil.isNotBlank(MapUtils.getString(map, "instruments"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "instruments")).size() > 0) {
                map.put("instruments", JSONUtil.parseArray(MapUtils.getString(map, "instruments")).toArray(String.class));
            } else {
                map.put("instruments", null);
            }
        }
        List<TradeGroupDTO> tradeGroup = tradeMapper.querysimpleTradeGroup(map);
        for (TradeGroupDTO tradeMap : tradeGroup) {
            if (map.get("accId") != null && map.get("accId") != "") {
                tradeMap.setAccId(Integer.parseInt((String) map.get("accId")));
            }
            if (map.get("tradeType") != null) {
                tradeMap.setTradeType((String) map.get("tradeType"));
            }
            if (map.get("begDate") != null) {
                tradeMap.setBegDate((String) map.get("begDate"));
            }
            if (map.get("endDate") != null) {
                tradeMap.setEndDate((String) map.get("endDate"));
            }
        }
        return tradeGroup;
    }


    /**
     * newCloud service 查询场外期权 交易
     */
    public List queryTrade4OtcOptionByPage(Map map) {
        return tradeMapper.queryTrade4OtcOptionByPage(map);
    }

    /**
     * newCloud service 查询场外期权和场内交易 交易
     */
    public List queryTradeDuration4OtcOptionByPage(Map map) {
        map.put("userId", SecurityUtils.getUserId());
        if (StrUtil.isNotBlank(MapUtils.getString(map, "iCodes"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "iCodes")).size() > 0) {
                map.put("iCodes", JSONUtil.parseArray(MapUtils.getString(map, "iCodes")).toArray(String.class));
            }
        }
        if (StrUtil.isNotBlank(MapUtils.getString(map, "tradeIds"))) {
            map.put("tradeIds", JSONUtil.parseArray(MapUtils.getString(map, "tradeIds")).toArray(String.class));
        }

        String tradeTypes = MapUtils.getString(map, "tradeTypes");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(tradeTypes)) {
            map.put("tradeTypes", tradeTypes.split(","));
        }

        String instruments = MapUtils.getString(map, "instruments");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(instruments)) {
            map.put("instruments", instruments.split("\\|"));
        }
        String accIds = MapUtils.getString(map, "accIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(accIds)) {
            map.put("accIds", accIds.split(","));
        }
        String eventStatuss = MapUtils.getString(map, "eventStatuss");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(eventStatuss)) {
            map.put("eventStatuss", eventStatuss.split(","));
        }
        String optionTypes = MapUtils.getString(map, "optionTypes");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(optionTypes)) {
            map.put("optionTypes", optionTypes.split(","));
        }
        String partyIds = MapUtils.getString(map, "partyIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(partyIds)) {
            map.put("partyIds", partyIds.split(","));
        }
        return tradeMapper.queryTradeDuration4OtcOptionByPage(map);
    }

    public List<TradeDurationDTO> queryTradeDuration4OtcOptionBalanceByPage(Map map) {
        return tradeMapper.queryTradeDuration4OtcOptionBalanceByPage(map);
    }

    /**
     * newCloud service 查询场外期权 交易
     */
    public List queryTradeOption4OtcOptionByPage(Map map) {
        return tradeMapper.queryTradeOption4OtcOptionByPage(map);
    }

    /**
     * newCloud service 查询组合  交易
     */
    public PageInfo<Trade> queryGroupBalanceByPage(Map map) {
        map.put("userId", SecurityUtils.getUserId());
        String tradeTypes = MapUtils.getString(map, "tradeTypes");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(tradeTypes)) {
            map.put("tradeTypes", tradeTypes.split(","));
        }
        String underlyerIds = MapUtils.getString(map, "underlyerIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(underlyerIds)) {
            map.put("underlyerIds", underlyerIds.split("\\|"));
        }
        String accIds = MapUtils.getString(map, "accIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(accIds)) {
            map.put("accIds", accIds.split(","));
        }
        String partyIds = MapUtils.getString(map, "partyIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(partyIds)) {
            map.put("partyIds", partyIds.split(","));
        }
        String optionTypes = MapUtils.getString(map, "optionTypes");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(optionTypes)) {
            map.put("optionTypes", optionTypes.split(","));
        }
        List<Trade> lst = tradeMapper.queryGroupBalanceByPage(map);
        return new PageInfo<>(lst);
    }

    /**
     * newCloud service 查询合约 下拉框
     */
    public List<Map> queryTradeContract(Map map) {
        return tradeMapper.queryTradeContract(map);
    }

    /**
     * newCloud service 导入 交易
     */
    @Transactional
    public CommResponse importTrades(HttpServletRequest request, MultipartFile cmf, String tradeType) throws Exception {
        TradeService service = tradeServiceFactory.getTradeService(tradeType);
        Map validMap = getValidList(service);
        CommResponse commResponse = service.importTrades(request, cmf, tradeType, validMap);
        if (commResponse.isSuccess()) {
            List list = (List) commResponse.getMsg();
            commResponse = insertTrades(list, tradeType);
        }
        TransferUtil.getCacheMap().put(Thread.currentThread().getId(), commResponse);
        return commResponse;
    }

    /**
     * newCloud service 导入 新增
     */
    public CommResponse insertTrades(List<Map> list, String tradeType) {
        CommResponse commResponse = new CommResponse(true);
        for (int i = 0; i < list.size(); i++) {
            Trade trade = BeanUtil.fillBeanWithMap(list.get(i), new Trade(), false);
            trade.setTradeStatus(1);
            trade.setSetDate(trade.getTradeDate());
            TradeService service = tradeServiceFactory.getTradeService(tradeType);
            //service.tranferTrade(trade);
            try {
                commResponse = service.insertTrade(trade);
                if (!commResponse.isSuccess()) {
                    commResponse.setMsg(commResponse.getMsg());
                    break;
                }
            } catch (Exception ex) {
                return CommResponse.failure("error", ex.getMessage(), "iCode", trade.getiCode());
            }
        }
        commResponse.setMsg("导入成功");
        return commResponse;
    }

    /**
     * 期权簿记导入
     *
     * @param uploadType 期权类型
     * @param file       文件
     * @return
     */
    public CommResponse importOtcOptionTrade(String uploadType, MultipartFile file) {
        CommResponse commResponse = new CommResponse(true);
        logger.info("导入文件类型:" + uploadType);
        logger.info("导入文件头:" + file.getContentType());
        switch (uploadType) {
            case "Vanilla":
                commResponse = importDigital(file);
                break;
            case "Digital":
                commResponse = importDigital(file);
                break;
            case "DoubleDigital":
                commResponse = importDigital(file);
                break;
            case "MultiDigital":
                commResponse = importDigital(file);
                break;
            case "Touch":
                commResponse = importDigital(file);
                break;
            case "SingleSharkFin":
                commResponse = importDigital(file);
                break;
            case "DoubleShark":
                commResponse = importDigital(file);
                break;
            case "RangeAccrual":
                commResponse = importDigital(file);
                break;
            case "BasicSnowball":
                commResponse = importDigital(file);
                break;

            case "Option":
                commResponse = importSummit(file, DictConstant.IMP_SOURCE.OPTIONS, SummitConstants.SUMMIT_IMPORT_TYPE.HAND);
                break;
            case "Must":
                commResponse = importSummit(file, DictConstant.IMP_SOURCE.MUST, SummitConstants.SUMMIT_IMPORT_TYPE.HAND);
                break;
        }
        return commResponse;
    }

    //导入期权簿记的校验和插入的委托方法
    private CommResponse insertTradeDelegation(Trade trade, Function<Trade, Map> func) {
        CommResponse commResponse = new CommResponse(true);
        //校验
        Map map = func.apply(trade);
        if ((boolean) map.get("OK") == true) {
            // 判断是否已经存在数据
            HashMap<String, String> param = new HashMap<>();
            param.put("iCode", trade.getiCode());
            if (tradeMapper.querySingleTradeContract(param).size() == 1) {
                Trade deleteTrade = new Trade();
                BeanUtil.copyProperties(trade, deleteTrade);
                deleteTrade(deleteTrade);
            }
            if (!SummitConstants.SUMMIT_ORDER_STATUS.CANC.equalsIgnoreCase(trade.getOrderStatus())) {
                //插入
                commResponse = insertTrade(trade);
            }
        } else {
            commResponse.setSuccess(false);
            commResponse.setMsg(map.get("msg"));
        }
        return commResponse;
    }


    /**
     * 导入Summit
     *
     * @param file
     * @param impSource 区分SummitOption 和SummitMust
     * @return
     */
    public CommResponse importSummit(MultipartFile file, String impSource, int importType) {
        CommResponse commResponse = new CommResponse(true);

        return commResponse;
    }

    class helloError {
        private String msg;
        private int offset;

        public String get原因() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public int get列序号() {
            return offset;
        }

        public void setOffset(int offset) {
            this.offset = offset;
        }
    }

    /**
     * 导入二元期权
     *
     * @param file
     * @return
     */
    public CommResponse importDigital(MultipartFile file) {
        CommResponse commResponse = new CommResponse(true);

        return commResponse;
    }


    /**
     * 二元期权导入实体类转换成trade
     */
    public Map digitalConvertToTrade(List<DigitalImportDto> list) throws Exception {
        List<Trade> tradeList = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();

        return resultMap;
    }

    public BigDecimal getDailyPrice(String instrumentId, String begDate) {
        Map<String, Object> dailyMap = new HashMap<>();
        String[] split = instrumentId.split(",");
        dailyMap.put("iCode", split[0]);
        dailyMap.put("aType", split[1]);
        dailyMap.put("mType", split[2]);
        dailyMap.put("begDate", begDate);
        //调用市场数据的dailyPrice方法
        Map dailyResultMap = remoteDailyPriceService.getdailypriceByBegDate(dailyMap);
        BigDecimal dpClose = new BigDecimal(BigInteger.ZERO);
        if (dailyResultMap != null) {
            dpClose = ParseUtils.converToBigDecimal(dailyResultMap.get("dpClose"));
        }
        return dpClose;
    }

    /**
     * newCloud service 导入 校验map
     */
    public Map getValidList(TradeService service) {
        Map map = new HashMap();
        List<Map<String, String>> columnCfglist = new ArrayList<>();
        for (int i = 0; i < 9; i++) {
            Map cfgmap = new HashMap();
            cfgmap.put("isImport", "1");
            columnCfglist.add(cfgmap);
        }
        List<String> headList = Arrays.asList("本方账户", "交易日期", "交易类型", "标的代码", "市场类型", "数量", "价格(元)", "金额(元)", "费用(元)");
        for (int i = 0; i < columnCfglist.size(); i++) {
            Map<String, String> columnCfgmap = columnCfglist.get(i);
            String head = headList.get(i);
            columnCfgmap.put("headName", head);
            columnCfgmap.put("allowBlank", "0");
        }
        // 本方账户校验
        Map<String, String> accountMap = columnCfglist.get(0);
        accountMap.put("colField", "accId");
        accountMap.put("colLength", "50");
        accountMap.put("colType", "STRING");
        accountMap.put("isTransfer", "1");

        // 交易日期校验
        Map<String, String> dateMap = columnCfglist.get(1);
        dateMap.put("colField", "tradeDate");
        dateMap.put("colLength", "50");
        dateMap.put("colType", "STRING");
        dateMap.put("isTransfer", "1");

        // 交易类型转化
        Map<String, String> typeMap = columnCfglist.get(2);
        typeMap.put("colField", "tradeType");
        typeMap.put("colLength", "50");
        typeMap.put("colType", "STRING");
        typeMap.put("isTransfer", "1");

        // 资产代码校验
        Map<String, String> iCodeMap = columnCfglist.get(3);
        iCodeMap.put("colField", "iCode");
        iCodeMap.put("colLength", "50");
        iCodeMap.put("colType", "STRING");
        iCodeMap.put("isTransfer", "1");

        // 市场类型校验
        Map<String, String> mTypeMap = columnCfglist.get(4);
        mTypeMap.put("colField", "mType");
        mTypeMap.put("colLength", "50");
        mTypeMap.put("colType", "STRING");
        mTypeMap.put("isInstrument", "1");

        // 数量校验
        Map<String, String> volumeMap = columnCfglist.get(5);
        volumeMap.put("colField", "volume");
        volumeMap.put("colLength", "50");
        volumeMap.put("colType", "NUMBER");
        volumeMap.put("allownegative", "1");

        // 价格校验
        Map<String, String> priceMap = columnCfglist.get(6);
        priceMap.put("colField", "price");
        priceMap.put("colLength", "50");
        priceMap.put("colType", "NUMBER");
        priceMap.put("allownegative", "1");

        // 金额校验
        Map<String, String> amountMap = columnCfglist.get(7);
        amountMap.put("colField", "amount");
        amountMap.put("colLength", "50");
        amountMap.put("colType", "NUMBER");
        amountMap.put("checkamount", "1");

        // 费用校验
        Map<String, String> feeMap = columnCfglist.get(8);
        feeMap.put("colField", "fee");
        feeMap.put("colLength", "50");
        feeMap.put("colType", "NUMBER");

        map.put("columnCfglist", columnCfglist);
        return map;
    }

    /**
     * newCloud service 新增交易
     */
    public CommResponse insertTrade(Trade trade) {
        // 刷新计算服务的行情信息
        notifyDataFacade.notifyDailySet();
        CacheUtil.getInstance().removeAllCacheData();

        TradeService service = tradeServiceFactory.getTradeService(trade.getTradeType());
        service.prepareTrade(trade);
        CommResponse ret = service.checkTrade(trade);
        if (ret.isSuccess()) {
            try {
                ret = service.insertTrade(trade);
            } catch (Exception ex) {
                ex.printStackTrace();
                return CommResponse.failure("error", ex.getMessage(), "iCode", trade.getiCode());
            }

        }
        return ret;
    }

    /**
     * newCloud service 审批前 校验
     */
    public CommResponse checkBeforeApproval(Trade trade) {
        Map<String, Map> map = new HashMap<>();
        TradeService service = tradeServiceFactory.getTradeService(trade.getTradeType());
        return service.checkBeforeApproval(trade, map);
    }

    /**
     * newCloud service 修改交易
     */
    public CommResponse updateTrade(Trade trade) {
        // 刷新计算服务的行情信息
        notifyDataFacade.notifyDailySet();
        CacheUtil.getInstance().removeAllCacheData();
        TradeService service = tradeServiceFactory.getTradeService(trade.getTradeType());
        service.prepareTrade(trade);
        CommResponse ret = service.checkTrade(trade);
        if (ret.isSuccess()) {
            try {
                ret = service.updateTrade(trade);
            } catch (Exception ex) {
                return CommResponse.failure(ex.getMessage());
            }
        }
        return ret;
    }

    /**
     * newCloud service 撤销前 校验
     */
    public CommResponse checkRevertTrade(Trade trade) {
        CommResponse ret = new CommResponse(true);

        return ret;
    }

    /**
     * newCloud service 撤销 交易
     */
    public CommResponse revertTrade(Trade trade) {
        TradeService service = tradeServiceFactory.getTradeService(trade.getTradeType());
        CommResponse ret = service.checkTrade(trade);
        if (ret.isSuccess()) {
            try {
                service.revertTrade(trade);
            } catch (Exception ex) {
                return CommResponse.failure(ex.getMessage());
            }
        }
        return ret;
    }

    /**
     * newCloud service 删除 交易
     */
    public CommResponse deleteTrade(Trade trade) {
        TradeService service = tradeServiceFactory.getTradeService(trade.getTradeType());
        service.prepareTrade(trade);
        if (trade.getTradeStatus().equals(0) || trade.getTradeStatus().equals(-2)) {
            service.deleteTrade(trade);
            return CommResponse.success();
        }
        CommResponse ret = service.checkTrade(trade);
        if (ret.isSuccess()) {
            try {
                service.deleteTrade(trade);
            } catch (Exception ex) {
                return CommResponse.failure(ex.getMessage());
            }
        }
        return ret;
    }

    public int queryTtradeCountByAccId(String accId) {
        return tradeMapper.queryTtradeCountByAccId(accId);
    }
}
